Skip to content

feat: add initial ARM64 (aarch64) architecture support#1875

Closed
tomassrnka wants to merge 11 commits intomainfrom
arm64-support
Closed

feat: add initial ARM64 (aarch64) architecture support#1875
tomassrnka wants to merge 11 commits intomainfrom
arm64-support

Conversation

@tomassrnka
Copy link
Copy Markdown
Member

@tomassrnka tomassrnka commented Feb 10, 2026

Summary

Adds ARM64/aarch64 architecture support to the E2B infrastructure, enabling builds and sandbox execution on Apple Silicon and other ARM64 hosts (via Lima VM + nested KVM).

Changes by commit:

  1. Makefiles — Replace hardcoded GOARCH=amd64 and --platform linux/amd64 with $(shell go env GOARCH) across all 4 service Makefiles
  2. Go runtime detection — Disable SMT on ARM64 (not supported), use runtime.GOARCH for OCI image platform, add ARM64 fallback for CPU detection (gopsutil doesn't populate Family/Model on ARM)
  3. Provision script — Make chattr calls non-fatal (|| true) for busybox versions that lack it
  4. create-build — Arch-aware Firecracker and kernel download URLs (tries arm64/ subdirectory first, falls back to generic), E2B_BASE_IMAGE env var for base image override
  5. fetch-busybox — Makefile target to swap the embedded x86 busybox binary with the system's ARM64 busybox-static before compilation

Related PRs:

Test plan

  • Build orchestrator, envd, API, and client-proxy natively on ARM64 Linux
  • Run make fetch-busybox on ARM64 host to swap busybox binary
  • Template build succeeds with create-build on ARM64
  • Sandbox create/exec/delete works on ARM64 (Lima VM + KVM)
  • Verify uname -m in sandbox returns aarch64
  • Confirm no regression on x86_64 builds (all changes are backwards compatible)

🤖 Generated with Claude Code


Note

High Risk
High risk because it changes core sandbox/Firecracker startup and snapshot handling (including disabling seccomp on ARM64) and alters kernel/Firecracker path resolution and OCI platform selection, which can impact both security posture and runtime stability across architectures.

Overview
Adds initial ARM64 support end-to-end by introducing an ARM64 PR workflow (cross-compile + native arm runners) and runner setup script, making service build/publish Makefiles architecture-aware, and teaching the orchestrator to resolve Firecracker/kernel artifacts and OCI pulls by TARGET_ARCH with legacy fallbacks. It also adjusts runtime behavior for ARM64 (disable SMT, tweak UFFD write-protect usage, pass --no-seccomp for Firecracker on ARM64), hardens/deflakes several concurrency and hugepage-related tests, and updates template/rootfs provisioning to better handle clock-skewed APT, missing chattr, static network setup, and ext4 repair retries.

Written by Cursor Bugbot for commit 5491da7. This will update automatically on new commits. Configure here.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 589a0596cb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +28 to +37
// On ARM64, gopsutil doesn't populate Family/Model from /proc/cpuinfo.
// Provide fallback values so callers don't get an error.
if (family == "" || model == "") && runtime.GOARCH == "arm64" {
if family == "" {
family = "arm64"
}
if model == "" {
model = "0"
}
} else if family == "" || model == "" {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make it cleaner

Suggested change
// On ARM64, gopsutil doesn't populate Family/Model from /proc/cpuinfo.
// Provide fallback values so callers don't get an error.
if (family == "" || model == "") && runtime.GOARCH == "arm64" {
if family == "" {
family = "arm64"
}
if model == "" {
model = "0"
}
} else if family == "" || model == "" {
// On ARM64, gopsutil doesn't populate Family/Model from /proc/cpuinfo.
// Provide fallback values so callers don't get an error.
if (runtime.GOARCH == "arm64") {
if family == "" {
family = "arm64"
}
if model == "" {
model = "0"
}
}
if family == "" || model == "" {

@tomassrnka tomassrnka marked this pull request as draft February 10, 2026 19:41
@tomassrnka
Copy link
Copy Markdown
Member Author

@cursoragent bugbot run

@cursor
Copy link
Copy Markdown

cursor bot commented Feb 10, 2026

Unable to authenticate your request. Please make sure to connect your GitHub account to Cursor. Go to Cursor

@tomassrnka
Copy link
Copy Markdown
Member Author

@cursoragent bugbot run

@tomassrnka
Copy link
Copy Markdown
Member Author

@claude review this draft PR


.PHONY: fetch-busybox
fetch-busybox:
@ARCH=$$(dpkg --print-architecture 2>/dev/null || echo "amd64"); \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fetch-busybox target uses dpkg --print-architecture to detect the arch, but TargetArch() uses TARGET_ARCH env var. If a user sets TARGET_ARCH=arm64 on an amd64 host, this target will still use the amd64 busybox (since dpkg returns amd64), but the build will be for arm64, causing a binary mismatch.

if err := download(ctx, archURL, dstPath, 0o644); err == nil {
return nil
} else if !errors.Is(err, errNotFound) {
return fmt.Errorf("failed to download arm64 kernel: %w", err)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For arm64, if the arch-specific download (line 424) fails with a non-404 error (network issue, permissions, etc.), the code returns immediately without trying the legacy fallback. This differs from the Firecracker logic below which falls through to legacy on any 404. Consider consistent fallback behavior.

hugePages bool,
) error {
smt := true
smt := runtime.GOARCH != "arm64"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SMT is disabled based on runtime.GOARCH (compile-time host arch), not TARGET_ARCH. If cross-compiling (TARGET_ARCH=arm64 on amd64 host), the binary will incorrectly enable SMT for ARM64 VMs. Should check the actual target arch or defer this to runtime detection.


echo "Making configuration immutable"
$BUSYBOX chattr +i /etc/resolv.conf
$BUSYBOX chattr +i /etc/resolv.conf 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silencing chattr failures could mask real issues beyond busybox compatibility. If chattr fails on a full-featured system due to filesystem type, permissions, or corrupted inodes, the script will continue silently. Consider checking if chattr exists first, or logging the failure reason.

@tomassrnka
Copy link
Copy Markdown
Member Author

@claude review this draft PR

@tomassrnka
Copy link
Copy Markdown
Member Author

Re: CI workflow deduplication (@jakubno's comment about matrix inside pr-tests.yml)

We'll handle this differently — the ARM64 tests need a self-hosted runner with specific setup (KVM, hugepages, unprivileged UFFD, NBD modules) which doesn't fit cleanly into a matrix with the standard amd64 runner. Keeping them as a separate workflow (pr-tests-arm64.yml) invoked from the main PR workflow is the cleaner approach for now. Can revisit once ARM64 runners are standardized.

e2b and others added 6 commits March 25, 2026 15:00
- Add TargetArch() utility for runtime architecture resolution with
  TARGET_ARCH env var override and alias normalization (x86_64↔amd64,
  aarch64↔arm64)
- Add BUILD_ARCH/BUILD_PLATFORM variables to api, client-proxy, envd,
  and orchestrator Makefiles (defaults to host GOARCH)
- Add fetch-busybox target for ARM64 busybox binary swap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- config.go: prefer arch-prefixed paths ({version}/{arch}/binary) with
  legacy flat path fallback for existing production nodes
- create-build: download from GCS with {version}/{arch}/ layout, legacy
  fallback only for amd64 and only on 404
- OCI: use TargetArch() for container image platform selection
- Tests for arch-prefixed vs legacy path precedence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- client.go: disable SMT on ARM64 (no hyperthreading, Firecracker
  rejects SMT=true on ARM)
- script_builder.go: disable seccomp on ARM64 (upstream FC aarch64
  filter missing userfaultfd syscall)
- userfaultfd.go: skip UFFD write-protection flag on ARM64 (kernel
  doesn't support it; KVM dirty log used instead for diff tracking)
- machineinfo: ARM64 fallback for CPU Family/Model when gopsutil
  doesn't populate them
- smoketest: use runtime.GOARCH instead of hardcoded amd64

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- pr-tests-arm64.yml: cross-compile all packages, run unit tests on
  self-hosted ARM64 runner with KVM, hugepages, and NBD
- setup-arm64-runner.sh: configure self-hosted runner for ARM64 tests
- pull-request.yml: invoke ARM64 test workflow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ARM64's weaker memory model reliably triggers races that x86 papers over:

- clean-nfs-cache: fd use-after-close between Scanner and Statter
  goroutines — pass directory path string instead of *os.File
- nbd/path_direct: loop variable capture in goroutine closure
- envd conversion_test: shared connect.Response across parallel subtests
  — use RunAndReturn to create fresh response per call
- errorcollector_test: plain bool and ctx variable reuse in concurrent
  test — use atomic.Bool and distinct context variables
- db/testutils: goose v3.26 SetDialect() races on package globals when
  parallel tests run migrations — serialize with sync.Mutex
- uffd/page_mmap: graceful skip on hugepage ENOMEM in CI
- async_wp_test: skip UFFD write-protection test on ARM64 (unsupported)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document architecture naming conventions, SMT behavior, cross-arch
deployment via TARGET_ARCH, and path resolution strategy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tomassrnka tomassrnka marked this pull request as ready for review March 25, 2026 14:16
Remove the ARM64 guard that skipped UFFD WP — ARM64 kernels 6.10+
support it (merged upstream in Linux 6.10). The orchestrator requires
kernel 6.10+ on ARM64 hosts.

- userfaultfd.go: remove runtime.GOARCH != "arm64" guard from WP flag
- async_wp_test.go: remove ARM64 test skip

CI runner (ubuntu-24.04-arm) runs kernel 6.14 which supports WP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cursor
Copy link
Copy Markdown

cursor bot commented Mar 25, 2026

PR Summary

Medium Risk
Touches sandbox runtime configuration, artifact path resolution, and image pulling platform selection; regressions could break VM startup or template builds on existing amd64 nodes if fallbacks or platform detection behave unexpectedly.

Overview
Adds initial arm64 support end-to-end by making builds and Docker platforms architecture-aware, introducing a normalized TARGET_ARCH override for runtime path resolution and OCI image pulls, and updating the orchestrator to use arch-prefixed kernel/Firecracker artifacts with legacy fallbacks and safer download semantics. It also adjusts Firecracker startup/runtime behavior for ARM64 (disable SMT, pass --no-seccomp to allow userfaultfd), adds ARM64 CI coverage and runner setup automation, and fixes multiple race conditions and flaky tests that surfaced under ARM64’s stricter race detection (goose migrations, connect responses, NBD goroutine captures, hugepage mmap, and concurrent test data structures).

Written by Cursor Bugbot for commit c9c2f76. This will update automatically on new commits. Configure here.

HTTP handler goroutines concurrently access shared slices and maps
without synchronization:
- receivedParts map: switch to sync.Map (matches pattern in later tests)
- partSizes slice: add sync.Mutex around append
- retryTimes slice: add sync.Mutex around append

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jakubno
Copy link
Copy Markdown
Member

jakubno commented Mar 27, 2026

Can we also run the integration tests? 🙏🏻
I'd appreciate to split this up into separate smaller PRs, e.g. Makefiles, code changes (here it could be even more smaller ones), test pipeline. It'll make the review loop much faster

tomassrnka and others added 2 commits March 27, 2026 14:38
- Remove unused StracePfx field/template var from script_builder.go
- Revert unrelated package-lock.json version drift from branch divergence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tomassrnka
Copy link
Copy Markdown
Member Author

ARM64 Support — PR Breakdown

The arm64-support branch has been split into 8 focused PRs for easier review:

# PR Description Dependencies
1 #2256 fix: data races in tests and NFS cache scanner None
2 #2253 refactor: simplify telemetry Stopwatch API None
3 #2258 feat: TargetArch() utility + arch-aware path resolution None
4 #2259 feat: ARM64 runtime guards (SMT, CPU info, seccomp, UFFD) #2258
5 #2260 feat: arch-aware downloads in create-build + fetch-busybox #2258
6 #2257 chore: parameterize BUILD_ARCH/BUILD_PLATFORM in Makefiles None
7 #2255 ci: ARM64 cross-compilation and unit test workflow All above
8 #2254 docs: ARM64 support in orchestrator README #2258

Merge order

#2256 (race fixes) ──┐
#2253 (telemetry)  ──┤
#2257 (Makefiles)  ──┼── independent, merge in any order
                     │
#2258 (TargetArch) ──┤── foundation PR
                     │
#2259 (runtime)    ──┤
#2260 (create-build)─┼── depend on #2258, parallel to each other
#2254 (docs)       ──┤
                     │
#2255 (CI workflow)──┘── merge last

Cleanup applied before split

Closing this issue — tracked by individual PRs above.

@tomassrnka tomassrnka closed this Mar 29, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Seccomp completely disabled on ARM64 Firecracker sandboxes
    • Added SeccompFilterPath() to check for custom seccomp filter with userfaultfd syscall; uses --seccomp-filter when available, only falls back to --no-seccomp if custom filter is missing.
  • ✅ Fixed: fetch-busybox downloads wrong architecture in cross-compilation
    • Changed apt-get download to explicitly request arm64 architecture and added post-download architecture validation to ensure the binary is actually aarch64.

Create PR

Or push these changes by commenting:

@cursor push dc30338e96
Preview (dc30338e96)
diff --git a/packages/orchestrator/Makefile b/packages/orchestrator/Makefile
--- a/packages/orchestrator/Makefile
+++ b/packages/orchestrator/Makefile
@@ -146,12 +146,17 @@
 	elif command -v apt-get >/dev/null 2>&1 && command -v dpkg-deb >/dev/null 2>&1; then \
 		echo "Fetching arm64 busybox via apt..."; \
 		TMPDIR=$$(mktemp -d); \
-		apt-get download busybox-static 2>/dev/null && \
-			dpkg-deb -x busybox-static_*.deb "$$TMPDIR" && \
+		apt-get download busybox-static:arm64 2>/dev/null && \
+			dpkg-deb -x busybox-static_*_arm64.deb "$$TMPDIR" && \
+			if ! file "$$TMPDIR/bin/busybox" 2>/dev/null | grep -q 'aarch64\|ARM aarch64'; then \
+				rm -rf "$$TMPDIR" busybox-static_*.deb; \
+				echo "⚠ Downloaded busybox is not arm64 architecture"; \
+				exit 1; \
+			fi && \
 			cp "$$TMPDIR/bin/busybox" "$$BUSYBOX_TARGET" && \
 			rm -rf "$$TMPDIR" busybox-static_*.deb && \
 			echo "✓ Replaced embedded busybox with arm64 binary (from busybox-static package)" || \
-			{ rm -rf "$$TMPDIR" busybox-static_*.deb; echo "⚠ apt-get download failed"; exit 1; }; \
+			{ rm -rf "$$TMPDIR" busybox-static_*.deb; echo "⚠ apt-get download failed (arm64 architecture may not be configured)"; exit 1; }; \
 	else \
 		echo "⚠ ARM64 busybox required but no method available to fetch it."; \
 		echo "  Options:"; \

diff --git a/packages/orchestrator/pkg/sandbox/fc/config.go b/packages/orchestrator/pkg/sandbox/fc/config.go
--- a/packages/orchestrator/pkg/sandbox/fc/config.go
+++ b/packages/orchestrator/pkg/sandbox/fc/config.go
@@ -13,6 +13,13 @@
 
 	FirecrackerBinaryName = "firecracker"
 
+	// SeccompFilterName is the name of the custom seccomp filter BPF file.
+	// On aarch64, the default Firecracker seccomp filter does not include the
+	// userfaultfd syscall (nr 282), which is required for UFFD-based snapshot
+	// restore. A custom filter that adds userfaultfd can be placed at:
+	//   {FirecrackerVersionsDir}/{version}/[{arch}/]seccomp-filter.bpf
+	SeccompFilterName = "seccomp-filter.bpf"
+
 	envsDisk     = "/mnt/disks/fc-envs/v1"
 	buildDirName = "builds"
 
@@ -55,6 +62,25 @@
 	return filepath.Join(config.FirecrackerVersionsDir, t.FirecrackerVersion, FirecrackerBinaryName)
 }
 
+// SeccompFilterPath returns the path to a custom seccomp filter BPF file if it exists.
+// Returns empty string if no custom filter is found. The custom filter should include
+// the userfaultfd syscall for UFFD-based snapshot restore on aarch64.
+func (t Config) SeccompFilterPath(config cfg.BuilderConfig) string {
+	// Check arch-prefixed path first ({version}/{arch}/seccomp-filter.bpf)
+	archPath := filepath.Join(config.FirecrackerVersionsDir, t.FirecrackerVersion, utils.TargetArch(), SeccompFilterName)
+	if _, err := os.Stat(archPath); err == nil {
+		return archPath
+	}
+
+	// Fall back to legacy flat path ({version}/seccomp-filter.bpf)
+	flatPath := filepath.Join(config.FirecrackerVersionsDir, t.FirecrackerVersion, SeccompFilterName)
+	if _, err := os.Stat(flatPath); err == nil {
+		return flatPath
+	}
+
+	return ""
+}
+
 type RootfsPaths struct {
 	TemplateVersion uint64
 	TemplateID      string

diff --git a/packages/orchestrator/pkg/sandbox/fc/config_test.go b/packages/orchestrator/pkg/sandbox/fc/config_test.go
--- a/packages/orchestrator/pkg/sandbox/fc/config_test.go
+++ b/packages/orchestrator/pkg/sandbox/fc/config_test.go
@@ -111,3 +111,69 @@
 	// Should prefer the arch-prefixed path
 	assert.Equal(t, filepath.Join(dir, "vmlinux-6.1.102", arch, "vmlinux.bin"), result)
 }
+
+func TestSeccompFilterPath_ArchPrefixed(t *testing.T) {
+	t.Parallel()
+	dir := t.TempDir()
+	arch := utils.TargetArch()
+
+	// Create the arch-prefixed seccomp filter
+	archDir := filepath.Join(dir, "v1.12.0", arch)
+	require.NoError(t, os.MkdirAll(archDir, 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(archDir, "seccomp-filter.bpf"), []byte("bpf"), 0o644))
+
+	config := cfg.BuilderConfig{FirecrackerVersionsDir: dir}
+	fc := Config{FirecrackerVersion: "v1.12.0"}
+
+	result := fc.SeccompFilterPath(config)
+
+	assert.Equal(t, filepath.Join(dir, "v1.12.0", arch, "seccomp-filter.bpf"), result)
+}
+
+func TestSeccompFilterPath_LegacyFallback(t *testing.T) {
+	t.Parallel()
+	dir := t.TempDir()
+
+	// Only create the legacy flat seccomp filter
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "v1.12.0"), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "v1.12.0", "seccomp-filter.bpf"), []byte("bpf"), 0o644))
+
+	config := cfg.BuilderConfig{FirecrackerVersionsDir: dir}
+	fc := Config{FirecrackerVersion: "v1.12.0"}
+
+	result := fc.SeccompFilterPath(config)
+
+	assert.Equal(t, filepath.Join(dir, "v1.12.0", "seccomp-filter.bpf"), result)
+}
+
+func TestSeccompFilterPath_NoneExists(t *testing.T) {
+	t.Parallel()
+	dir := t.TempDir()
+
+	// No seccomp filter — should return empty string
+	config := cfg.BuilderConfig{FirecrackerVersionsDir: dir}
+	fc := Config{FirecrackerVersion: "v1.12.0"}
+
+	result := fc.SeccompFilterPath(config)
+
+	assert.Equal(t, "", result)
+}
+
+func TestSeccompFilterPath_PrefersArchOverLegacy(t *testing.T) {
+	t.Parallel()
+	dir := t.TempDir()
+	arch := utils.TargetArch()
+
+	// Create BOTH arch-prefixed and legacy flat seccomp filters
+	require.NoError(t, os.MkdirAll(filepath.Join(dir, "v1.12.0", arch), 0o755))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "v1.12.0", arch, "seccomp-filter.bpf"), []byte("arch-bpf"), 0o644))
+	require.NoError(t, os.WriteFile(filepath.Join(dir, "v1.12.0", "seccomp-filter.bpf"), []byte("legacy-bpf"), 0o644))
+
+	config := cfg.BuilderConfig{FirecrackerVersionsDir: dir}
+	fc := Config{FirecrackerVersion: "v1.12.0"}
+
+	result := fc.SeccompFilterPath(config)
+
+	// Should prefer the arch-prefixed path
+	assert.Equal(t, filepath.Join(dir, "v1.12.0", arch, "seccomp-filter.bpf"), result)
+}

diff --git a/packages/orchestrator/pkg/sandbox/fc/script_builder.go b/packages/orchestrator/pkg/sandbox/fc/script_builder.go
--- a/packages/orchestrator/pkg/sandbox/fc/script_builder.go
+++ b/packages/orchestrator/pkg/sandbox/fc/script_builder.go
@@ -87,13 +87,20 @@
 	rootfsPaths RootfsPaths,
 	namespaceID string,
 ) startScriptArgs {
-	// On ARM64, disable seccomp to allow userfaultfd syscall for snapshot restore.
-	// The upstream Firecracker seccomp filter for aarch64 does not include the
-	// userfaultfd syscall (nr 282), causing snapshot loading to fail with
-	// "Failed to UFFD object: System error".
+	// On ARM64, we need to handle seccomp specially because the upstream Firecracker
+	// seccomp filter for aarch64 does not include the userfaultfd syscall (nr 282),
+	// which is required for UFFD-based snapshot restore.
+	//
+	// If a custom seccomp filter is available (seccomp-filter.bpf), use it via
+	// --seccomp-filter. This custom filter should be the default aarch64 filter
+	// with userfaultfd added. If no custom filter exists, fall back to --no-seccomp.
 	var extraArgs string
 	if runtime.GOARCH == "arm64" {
-		extraArgs = " --no-seccomp"
+		if filterPath := versions.SeccompFilterPath(sb.builderConfig); filterPath != "" {
+			extraArgs = " --seccomp-filter " + filterPath
+		} else {
+			extraArgs = " --no-seccomp"
+		}
 	}
 
 	return startScriptArgs{

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

var extraArgs string
if runtime.GOARCH == "arm64" {
extraArgs = " --no-seccomp"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seccomp completely disabled on ARM64 Firecracker sandboxes

High Severity

On ARM64, --no-seccomp is appended to the Firecracker command, completely disabling the seccomp sandbox rather than just allowing the missing userfaultfd syscall. This removes an entire security boundary for all sandbox processes on ARM64 hosts. Firecracker supports custom seccomp filters via --seccomp-filter which could allowlist only the needed userfaultfd syscall (nr 282) while keeping all other restrictions intact.

Fix in Cursor Fix in Web

cp "$$TMPDIR/bin/busybox" "$$BUSYBOX_TARGET" && \
rm -rf "$$TMPDIR" busybox-static_*.deb && \
echo "✓ Replaced embedded busybox with arm64 binary (from busybox-static package)" || \
{ rm -rf "$$TMPDIR" busybox-static_*.deb; echo "⚠ apt-get download failed"; exit 1; }; \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetch-busybox downloads wrong architecture in cross-compilation

Low Severity

When BUILD_ARCH=arm64 is set on an amd64 host (cross-compilation), the apt-get download busybox-static fallback downloads the host architecture package (amd64), not arm64. The script then silently embeds the wrong-architecture busybox binary into the build, since there's no post-download architecture validation via file in this code path (unlike the host-busybox check in the elif above).

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants